#include "base/logcontent.h"
using namespace Base::Log;

CLogContent::CLogContent()
{
    m_pwstrLogFilter = new std::wstring;
    m_pwstrModuleName = new std::wstring;
    m_pwstrFileName = new std::wstring;
    m_pwstrFunctionName = new std::wstring;
    m_pwstrLogContent = new std::wstring;
}

CLogContent::~CLogContent()
{
    delete m_pwstrLogFilter;
    delete m_pwstrModuleName;
    delete m_pwstrFileName;
    delete m_pwstrFunctionName;
    delete m_pwstrLogContent;
}

void CLogContent::SetLogInfoBuffer(const void* pInfoBuffer, const DWORD dwBufferSize)
{
    if (!pInfoBuffer || dwBufferSize == 0)
    {
        return ;
    }

    const char* pBuffer = reinterpret_cast<const char*>(pInfoBuffer);
    std::wstring::size_type offset = 0;

    memcpy_s(
        &m_logType,
        sizeof(Base::Log::Type),
        pBuffer + offset,
        sizeof(Base::Log::Type)
        );

    offset += sizeof(Base::Log::Type);
    memcpy_s(
        &m_dwProcessID,
        sizeof(DWORD),
        pBuffer + offset,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        &m_dwThreadID,
        sizeof(DWORD),
        pBuffer + offset,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        &m_dwLineNumber,
        sizeof(DWORD),
        pBuffer + offset,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        &m_logTime,
        sizeof(SYSTEMTIME),
        pBuffer + offset,
        sizeof(SYSTEMTIME)
        );

    offset += sizeof(SYSTEMTIME);
    GetStringFromBuffer(pBuffer, offset, *m_pwstrLogFilter);
    GetStringFromBuffer(pBuffer, offset, *m_pwstrModuleName);
    GetStringFromBuffer(pBuffer, offset, *m_pwstrFileName);
    GetStringFromBuffer(pBuffer, offset, *m_pwstrFunctionName);
    GetStringFromBuffer(pBuffer, offset, *m_pwstrLogContent);
}

void CLogContent::GetLogInfoBuffer(void** ppBufferRecv, DWORD& dwBufferSize) const
{
    if (!ppBufferRecv)
    {
        return ;
    }

    dwBufferSize = static_cast<DWORD>(
        sizeof(Base::Log::Type) + sizeof(DWORD) * 3 + sizeof(SYSTEMTIME)
        + sizeof(std::wstring::size_type) + sizeof(wchar_t) * m_pwstrLogFilter->size()
        + sizeof(std::wstring::size_type) + sizeof(wchar_t) * m_pwstrModuleName->size()
        + sizeof(std::wstring::size_type) + sizeof(wchar_t) * m_pwstrFileName->size()
        + sizeof(std::wstring::size_type) + sizeof(wchar_t) * m_pwstrFunctionName->size()
        + sizeof(std::wstring::size_type) + sizeof(wchar_t) * m_pwstrLogContent->size()
        );

    *ppBufferRecv = new char[dwBufferSize];
    char* pBuffer = reinterpret_cast<char*>(*ppBufferRecv);
    std::wstring::size_type offset = 0;

    memcpy_s(
        pBuffer + offset,
        sizeof(Base::Log::Type),
        &m_logType,
        sizeof(Base::Log::Type)
        );

    offset += sizeof(Base::Log::Type);
    memcpy_s(
        pBuffer + offset,
        sizeof(DWORD),
        &m_dwProcessID,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        pBuffer + offset,
        sizeof(DWORD),
        &m_dwThreadID,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        pBuffer + offset,
        sizeof(DWORD),
        &m_dwLineNumber,
        sizeof(DWORD)
        );

    offset += sizeof(DWORD);
    memcpy_s(
        pBuffer + offset,
        sizeof(SYSTEMTIME),
        &m_logTime,
        sizeof(SYSTEMTIME)
        );

    offset += sizeof(SYSTEMTIME);
    CopyStringToBuffer(pBuffer, offset, *m_pwstrLogFilter);
    CopyStringToBuffer(pBuffer, offset, *m_pwstrModuleName);
    CopyStringToBuffer(pBuffer, offset, *m_pwstrFileName);
    CopyStringToBuffer(pBuffer, offset, *m_pwstrFunctionName);
    CopyStringToBuffer(pBuffer, offset, *m_pwstrLogContent);
}

void CLogContent::GetStringFromBuffer(const char* pBuffer,std::wstring::size_type& offset,std::wstring& wstr)
{
    std::wstring::size_type charCnt = 0;
    memcpy_s(
        &charCnt,
        sizeof(std::wstring::size_type),
        pBuffer + offset,
        sizeof(std::wstring::size_type)
        );

    offset += sizeof(std::wstring::size_type);
    if (charCnt > 0)
    {
        wchar_t* wszStr = new wchar_t[charCnt + 1];
        std::wstring::size_type len = sizeof(wchar_t) * charCnt;
        memcpy_s(
            wszStr,
            len,
            pBuffer + offset,
            len
            );

        wszStr[charCnt] = 0;
        wstr = wszStr;
        delete [] wszStr;

        offset += len;
    }
}

void CLogContent::CopyStringToBuffer(char* pBuffer,std::wstring::size_type& offset,const std::wstring& wstr) const
{
    std::wstring::size_type charCnt = wstr.size();
    memcpy_s(
        pBuffer + offset,
        sizeof(std::wstring::size_type),
        &charCnt,
        sizeof(std::wstring::size_type)
        );

    offset += sizeof(std::wstring::size_type);
    if (!wstr.empty())
    {
        const std::wstring::size_type len = charCnt * sizeof(wchar_t);
        memcpy_s(
            pBuffer + offset,
            len,
            wstr.c_str(),
            len
            );

        offset += len;
    }
}